home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / directx / dxf / extras / direct3d / tools / 3dsmax3 / meshdata.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-22  |  19.9 KB  |  545 lines

  1. //-----------------------------------------------------------------------------
  2. // File: MeshData.cpp
  3. //
  4. // Desc: Functions used to massage mesh data into a format useable in X Files
  5. //
  6. // Copyright (C) 1998-2000 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8.  
  9. #include "pch.h"
  10. #include "MeshData.h"
  11.  
  12. BOOL FindIdenticalVertex
  13.     (
  14.     SMeshData *pMeshData, 
  15.     DWORD iVertexIndex, 
  16.     DWORD iSmoothingGroup, 
  17.     DWORD iTextureIndex,
  18.     DWORD *piVertex
  19.     )
  20. {
  21.     DWORD iHeadVertex;
  22.     DWORD iCurVertex;
  23.  
  24.     // walk the wedge list to see if any of the other vertice have the same smoothing and texture index
  25.     iHeadVertex = iVertexIndex;
  26.     iCurVertex = iHeadVertex;
  27.     do
  28.     {
  29.         // if identical requirements, then return true with the vertex index
  30.         if ((pMeshData->m_rgVertices[iCurVertex].iSmoothingGroupIndex == iSmoothingGroup)
  31.             && (pMeshData->m_rgVertices[iCurVertex].iTextureIndex == iTextureIndex) )
  32.         {
  33.             *piVertex = iCurVertex;
  34.             return TRUE;
  35.         }
  36.  
  37.         // move to next element of wedge list and check to see if we wrapped (circular list)
  38.         iCurVertex = pMeshData->m_rgVertices[iCurVertex].iWedgeList;
  39.     }
  40.     while (iHeadVertex != iCurVertex);
  41.  
  42.     return FALSE;
  43. }
  44.  
  45. void AddNormalContribution
  46.     (
  47.     SMeshData *pMeshData,
  48.     DWORD iVertexIndex, 
  49.     DWORD iSmoothingGroup,
  50.     Point3 vNormal 
  51.     )
  52. {
  53.     DWORD iHeadVertex;
  54.     DWORD iCurVertex;
  55.  
  56.     // walk the wedge list to find other split vertices with the same smoothing group
  57.     iHeadVertex = iVertexIndex;
  58.     iCurVertex = iHeadVertex;
  59.     do
  60.     {
  61.         // if same smoothing group add the normal in
  62.         if (pMeshData->m_rgVertices[iCurVertex].iSmoothingGroupIndex == iSmoothingGroup)    
  63.         {
  64.             pMeshData->m_rgVertices[iCurVertex].vNormal += vNormal;
  65.         }
  66.  
  67.         // move to next element of wedge list and check to see if we wrapped (circular list)
  68.         iCurVertex = pMeshData->m_rgVertices[iCurVertex].iWedgeList;
  69.     }
  70.     while (iHeadVertex != iCurVertex);
  71.  
  72. }
  73.  
  74. HRESULT GenerateMeshData
  75.     (
  76.     Mesh *pMesh,
  77.     SMeshData *pMeshData 
  78.     )
  79. {
  80.     HRESULT hr = S_OK;
  81.     BOOL *rgbVertexReferencedArray = NULL;
  82.     DWORD cVerticesMax;
  83.     DWORD iRawVertexIndex;
  84.     DWORD iTextureIndex;
  85.     DWORD iSmoothingGroupIndex;
  86.     DWORD iVertex;
  87.     DWORD iFace;
  88.     DWORD iPoint;
  89.     DWORD iNewVertex;
  90.     BOOL bFound;
  91.     SVertexData *rgVerticesNew;
  92.  
  93.     assert(pMesh != NULL);
  94.     assert(pMeshData != NULL);
  95.  
  96.     pMeshData->m_bTexCoordsPresent = FALSE;
  97.     pMeshData->m_cFaces = pMesh->numFaces;
  98.     pMeshData->m_cVertices = pMesh->numVerts;
  99.     pMeshData->m_cVerticesBeforeDuplication = pMesh->numVerts;
  100.     cVerticesMax = pMesh->numVerts;
  101.  
  102.     pMeshData->m_rgVertices = new SVertexData[cVerticesMax];
  103.     pMeshData->m_rgFaces = new SFaceData[pMeshData->m_cFaces];
  104.     rgbVertexReferencedArray = new BOOL[pMeshData->m_cVerticesBeforeDuplication];
  105.  
  106.     if ((pMeshData ->m_rgVertices == NULL) 
  107.             || (pMeshData ->m_rgFaces == NULL)
  108.             || (rgbVertexReferencedArray == NULL))
  109.     {
  110.         hr = E_OUTOFMEMORY;
  111.         goto e_Exit;
  112.     }
  113.  
  114.     if( !(pMesh->normalsBuilt) )
  115.     {
  116.         pMesh->checkNormals(TRUE);
  117.     }
  118.  
  119.     // Initialize vertex node list so that first batch are the same as the
  120.     // vertex array in the mesh.  Duplicated vertices will be appended to the list.
  121.     // The first time a vertex comes up in face enumeration below, the initial vertex
  122.     // node added here will be modified to reflect the smoothing and texture info.
  123.     // When the vertex comes up again with different smoothing or texture info, the
  124.     // vertex will be duplicated and appended to the list.
  125.     for (iVertex = 0; iVertex < pMeshData->m_cVertices; iVertex++ )
  126.     {
  127.         rgbVertexReferencedArray[iVertex] = FALSE;
  128.  
  129.         pMeshData->m_rgVertices[iVertex].iPointRep = iVertex;
  130.         pMeshData->m_rgVertices[iVertex].iWedgeList = iVertex;
  131.  
  132.         // default values that should be reset if the vertex is actually used by a face...
  133.         pMeshData->m_rgVertices[iVertex].vNormal.x = 0;
  134.         pMeshData->m_rgVertices[iVertex].vNormal.y = 0;
  135.         pMeshData->m_rgVertices[iVertex].vNormal.z = 0;
  136.         pMeshData->m_rgVertices[iVertex].iSmoothingGroupIndex = 0;
  137.         pMeshData->m_rgVertices[iVertex].iTextureIndex = 0;
  138.     }
  139.     
  140.     // for each face, add the face normal for each corner to the vertex node list array.
  141.     // The index into the vertex node list array is just the vertex index, and a list of CVertexNodes
  142.     // is built for the unique smoothing groups for that vertex.  Each CVertexNode holds the normal
  143.     // at that vertex based on a particular smoothing group.  All CVertexNodes get an index, and
  144.     // the list of CFaceIndices is a face list with the corners updated with the new expanded vertex
  145.     // indices (CVertexNode index).
  146.     //
  147.     // Added: Now CVertexNodes each represent a unique smoothing group + texture coordinate set
  148.     // for a vertex.
  149.     for( iFace = 0; iFace < pMeshData->m_cFaces; iFace++ )
  150.     {
  151.         for( iPoint = 0; iPoint < 3; iPoint++ ) // vertex indices
  152.         {
  153.             iRawVertexIndex = pMesh->faces[iFace].v[iPoint];
  154.             iTextureIndex = 0xFFFFFFFF;
  155.             iSmoothingGroupIndex = pMesh->faces[iFace].smGroup;
  156.  
  157.             if ((pMesh->faces[iFace].flags & HAS_TVERTS) 
  158.                     && (NULL != pMesh->tvFace)
  159.                     && ((int)pMesh->tvFace[iFace].t[iPoint] < pMesh->numTVerts) )
  160.             {
  161.                 pMeshData->m_bTexCoordsPresent = TRUE;
  162.  
  163.                 iTextureIndex = pMesh->tvFace[iFace].t[iPoint];
  164.             }
  165.             
  166.             if (FALSE == rgbVertexReferencedArray[iRawVertexIndex])
  167.             {
  168.                 // first reference to this vertex.
  169.                 rgbVertexReferencedArray[iRawVertexIndex] = TRUE;
  170.  
  171.                 pMeshData->m_rgVertices[iRawVertexIndex].iSmoothingGroupIndex = iSmoothingGroupIndex;
  172.                 pMeshData->m_rgVertices[iRawVertexIndex].iTextureIndex = iTextureIndex;
  173.  
  174.                 pMeshData->m_rgFaces[iFace].index[iPoint] = iRawVertexIndex;
  175.             }
  176.             else
  177.             {
  178.                 // need to remember the index
  179.                 bFound = FindIdenticalVertex(pMeshData, iRawVertexIndex, iSmoothingGroupIndex, iTextureIndex, &iNewVertex);
  180.  
  181.                 // if not found, then split out another vertex
  182.                 if (!bFound)
  183.                 {
  184.                     // realloc if array too small
  185.                     if (pMeshData->m_cVertices == cVerticesMax)
  186.                     {
  187.                         cVerticesMax = cVerticesMax * 2;
  188.                         rgVerticesNew = new SVertexData[cVerticesMax];
  189.                         if (rgVerticesNew == NULL)
  190.                         {
  191.                             hr = E_OUTOFMEMORY;
  192.                             goto e_Exit;
  193.                         }
  194.  
  195.                         memcpy(rgVerticesNew, pMeshData->m_rgVertices, sizeof(SVertexData) * pMeshData->m_cVertices);
  196.  
  197.                         delete []pMeshData->m_rgVertices;
  198.                         pMeshData->m_rgVertices = rgVerticesNew;
  199.                     }
  200.  
  201.                     // grab the next spot in the array
  202.                     iNewVertex = pMeshData->m_cVertices;
  203.                     pMeshData->m_cVertices += 1;
  204.  
  205.                     // setup point rep and wedge list
  206.                     pMeshData->m_rgVertices[iNewVertex].iPointRep = iRawVertexIndex;
  207.  
  208.                     // link into wedge list of point rep
  209.                     pMeshData->m_rgVertices[iNewVertex].iWedgeList = pMeshData->m_rgVertices[iRawVertexIndex].iWedgeList;
  210.                     pMeshData->m_rgVertices[iRawVertexIndex].iWedgeList = iNewVertex;
  211.  
  212.                     // setup vertex info
  213.                     pMeshData->m_rgVertices[iNewVertex].vNormal.x = 0;
  214.                     pMeshData->m_rgVertices[iNewVertex].vNormal.y = 0;
  215.                     pMeshData->m_rgVertices[iNewVertex].vNormal.z = 0;
  216.                     pMeshData->m_rgVertices[iNewVertex].iSmoothingGroupIndex = iSmoothingGroupIndex;
  217.                     pMeshData->m_rgVertices[iNewVertex].iTextureIndex = iTextureIndex;
  218.                 }
  219.  
  220.                 pMeshData->m_rgFaces[iFace].index[iPoint] = iNewVertex;
  221.             }
  222.  
  223.             // add normal contribution to every vertex with this rawVertexIndex and
  224.             // this smoothinggroup
  225.             AddNormalContribution(pMeshData, iRawVertexIndex, iSmoothingGroupIndex, pMesh->getFaceNormal(iFace));
  226.         }
  227.     }
  228.  
  229.     for (iVertex = 0; iVertex < pMeshData->m_cVertices; iVertex++)
  230.     {
  231.         pMeshData->m_rgVertices[iVertex].vNormal.Normalize();
  232.     }
  233.  
  234. e_Exit:
  235.     delete[] rgbVertexReferencedArray;
  236.  
  237.     return hr;
  238. }
  239.  
  240.  
  241.  
  242. BOOL FindIdenticalPatchVertex
  243.     (
  244.     SPatchMeshData *pPatchMeshData, 
  245.     DWORD iVertexIndex, 
  246.     DWORD iTextureIndex,
  247.     DWORD *piVertex
  248.     )
  249. {
  250.     DWORD iHeadVertex;
  251.     DWORD iCurVertex;
  252.  
  253.     // walk the wedge list to see if any of the other vertice have the same smoothing and texture index
  254.     iHeadVertex = iVertexIndex;
  255.     iCurVertex = iHeadVertex;
  256.     do
  257.     {
  258.         // if identical requirements, then return true with the vertex index
  259.         if (pPatchMeshData->m_rgVertices[iCurVertex].iTextureIndex == iTextureIndex)
  260.         {
  261.             *piVertex = iCurVertex;
  262.             return TRUE;
  263.         }
  264.  
  265.         // move to next element of wedge list and check to see if we wrapped (circular list)
  266.         iCurVertex = pPatchMeshData->m_rgVertices[iCurVertex].iWedgeList;
  267.     }
  268.     while (iHeadVertex != iCurVertex);
  269.  
  270.     return FALSE;
  271. }
  272.  
  273. HRESULT GeneratePatchMeshData
  274.     (
  275.     PatchMesh *pPatchMesh,
  276.     SPatchMeshData *pPatchMeshData 
  277.     )
  278. {
  279.     HRESULT hr = S_OK;
  280.     BYTE *rgbVertexReferencedArray = NULL;
  281.     DWORD cVerticesMax;
  282.     DWORD iRawVertexIndex;
  283.     DWORD iTextureIndex;
  284.     DWORD iVertex;
  285.     DWORD iPoint;
  286.     DWORD iNewVertex;
  287.     BOOL bFound;
  288.     SPatchVertexData *rgVerticesNew;
  289.     DWORD iCurVertex;
  290.     DWORD iPatch;
  291.     DWORD cPoints;
  292.     PatchVec *pvPatchVecs;
  293.     Patch *pPatch;
  294.     DWORD *rgdwControl;
  295.  
  296.     assert(pPatchMesh != NULL);
  297.     assert(pPatchMeshData != NULL);
  298.  
  299.     pPatchMeshData->m_bTexCoordsPresent = FALSE;
  300.     pPatchMeshData->m_cPatches = pPatchMesh->numPatches;
  301.  
  302.     // UNDONE - need to refine
  303.     cVerticesMax = pPatchMeshData->m_cPatches * 16;
  304.  
  305.     pPatchMeshData->m_rgVertices = new SPatchVertexData[cVerticesMax];
  306.     pPatchMeshData->m_rgPatches = new SPatchData[pPatchMesh->numPatches];
  307.  
  308.     if ((pPatchMeshData->m_rgVertices == NULL) 
  309.             || (pPatchMeshData->m_rgPatches == NULL))
  310.     {
  311.         hr = E_OUTOFMEMORY;
  312.         goto e_Exit;
  313.     }
  314.  
  315.     // initialize the verts being copied from the pPatchMesh->verts array
  316.     for (iVertex = 0; iVertex < pPatchMesh->numVerts; iVertex++)
  317.     {
  318.         pPatchMeshData->m_rgVertices[iVertex].vPosition = pPatchMesh->verts[iVertex].p;
  319.  
  320.         pPatchMeshData->m_rgVertices[iVertex].iPointRep = iVertex;
  321.         pPatchMeshData->m_rgVertices[iVertex].iWedgeList = iVertex;
  322.  
  323.         pPatchMeshData->m_rgVertices[iVertex].iTextureIndex = 0;
  324.     }
  325.  
  326.     // for the rest of vers, init the non position fields, position filled in when
  327.     //   reading patches
  328.     iCurVertex = pPatchMesh->numVerts;
  329.     for (iVertex = iCurVertex; iVertex < cVerticesMax; iVertex++)
  330.     {
  331.         pPatchMeshData->m_rgVertices[iVertex].iPointRep = iVertex;
  332.         pPatchMeshData->m_rgVertices[iVertex].iWedgeList = iVertex;
  333.  
  334.         pPatchMeshData->m_rgVertices[iVertex].iTextureIndex = 0;
  335.     }
  336.  
  337.  
  338.     pvPatchVecs = pPatchMesh->vecs;
  339.     for (iPatch = 0; iPatch < pPatchMesh->numPatches; iPatch++)
  340.     {
  341.         pPatch = &pPatchMesh->patches[iPatch];
  342.  
  343.         if (pPatch->type == PATCH_TRI)
  344.         {
  345.             // nControlIndices
  346.             pPatchMeshData->m_rgPatches[iPatch].m_cControl = 10;
  347.  
  348.             rgdwControl = pPatchMeshData->m_rgPatches[iPatch].m_rgdwControl;
  349.             rgdwControl[0] = pPatch->v[0];
  350.             rgdwControl[3] = pPatch->v[1];
  351.             rgdwControl[6] = pPatch->v[2];
  352.  
  353.             rgdwControl[1] = iCurVertex;
  354.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[0]].p;
  355.             iCurVertex += 1;
  356.         
  357.             rgdwControl[2] = iCurVertex;
  358.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[1]].p;
  359.             iCurVertex += 1;
  360.         
  361.             rgdwControl[4] = iCurVertex;
  362.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[2]].p;
  363.             iCurVertex += 1;
  364.         
  365.             rgdwControl[5] = iCurVertex;
  366.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[3]].p;
  367.             iCurVertex += 1;
  368.         
  369.             rgdwControl[7] = iCurVertex;
  370.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[4]].p;
  371.             iCurVertex += 1;
  372.         
  373.             rgdwControl[8] = iCurVertex;
  374.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[5]].p;
  375.             iCurVertex += 1;
  376.         
  377.             // UNDONE - is the correct way to get a single interior control
  378.             //  point from 3ds max
  379.             rgdwControl[9] = iCurVertex;
  380.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->interior[0]].p;
  381.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition += pvPatchVecs[pPatch->interior[1]].p;
  382.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition += pvPatchVecs[pPatch->interior[2]].p;
  383.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition /= 3;
  384.             iCurVertex += 1;
  385.         }
  386.         else if (pPatch->type == PATCH_QUAD)
  387.         {
  388.             // nControlIndices
  389.             pPatchMeshData->m_rgPatches[iPatch].m_cControl = 16;
  390.  
  391.             rgdwControl = pPatchMeshData->m_rgPatches[iPatch].m_rgdwControl;
  392.             rgdwControl[0] = pPatch->v[0];
  393.             rgdwControl[3] = pPatch->v[1];
  394.             rgdwControl[6] = pPatch->v[2];
  395.             rgdwControl[9] = pPatch->v[3];
  396.  
  397.             rgdwControl[1] = iCurVertex;
  398.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[0]].p;
  399.             iCurVertex += 1;
  400.         
  401.             rgdwControl[2] = iCurVertex;
  402.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[1]].p;
  403.             iCurVertex += 1;
  404.         
  405.             rgdwControl[4] = iCurVertex;
  406.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[2]].p;
  407.             iCurVertex += 1;
  408.         
  409.             rgdwControl[5] = iCurVertex;
  410.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[3]].p;
  411.             iCurVertex += 1;
  412.         
  413.             rgdwControl[7] = iCurVertex;
  414.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[4]].p;
  415.             iCurVertex += 1;
  416.         
  417.             rgdwControl[8] = iCurVertex;
  418.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[5]].p;
  419.             iCurVertex += 1;
  420.         
  421.             rgdwControl[10] = iCurVertex;
  422.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[6]].p;
  423.             iCurVertex += 1;
  424.  
  425.             rgdwControl[11] = iCurVertex;
  426.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->vec[7]].p;
  427.             iCurVertex += 1;
  428.  
  429.             rgdwControl[12] = iCurVertex;
  430.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->interior[0]].p;
  431.             iCurVertex += 1;
  432.  
  433.             rgdwControl[13] = iCurVertex;
  434.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->interior[1]].p;
  435.             iCurVertex += 1;
  436.  
  437.             rgdwControl[14] = iCurVertex;
  438.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->interior[2]].p;
  439.             iCurVertex += 1;
  440.  
  441.             rgdwControl[15] = iCurVertex;
  442.             pPatchMeshData->m_rgVertices[iCurVertex].vPosition = pvPatchVecs[pPatch->interior[3]].p;
  443.             iCurVertex += 1;
  444.         }
  445.         else // undefined patch type
  446.         {
  447.             hr = E_INVALIDARG;
  448.             goto e_Exit;
  449.         }
  450.     }
  451.  
  452.     // now record the initial number of vertices
  453.     pPatchMeshData->m_cVerticesBeforeDuplication = iCurVertex;
  454.     pPatchMeshData->m_cVertices = iCurVertex;
  455.  
  456.     rgbVertexReferencedArray = new BYTE[pPatchMeshData->m_cVertices];
  457.     if (rgbVertexReferencedArray == NULL)
  458.     {
  459.         hr = E_OUTOFMEMORY;
  460.         goto e_Exit;
  461.     }
  462.     memset(rgbVertexReferencedArray, 0, sizeof(BYTE) * pPatchMeshData->m_cVertices);
  463.  
  464.     for( iPatch = 0; iPatch < pPatchMeshData->m_cPatches; iPatch++ )
  465.     {
  466.         cPoints = (pPatchMeshData->m_rgPatches[iPatch].m_cControl == 10) ? 3 : 4;
  467.         for( iPoint = 0; iPoint < cPoints; iPoint++ ) 
  468.         {
  469.             iTextureIndex = 0xFFFFFFFF;
  470.             iRawVertexIndex = pPatchMeshData->m_rgPatches[iPatch].m_rgdwControl[iPoint * 3];
  471.  
  472.             // try to get a texture index
  473.             if ((pPatchMesh->tvPatches.Count() >= 2) && (pPatchMesh->tvPatches[1] != NULL))
  474.             {
  475.                 iTextureIndex = pPatchMesh->tvPatches[1][iPatch].tv[iPoint];
  476.                 if (iTextureIndex < pPatchMesh->numTVerts[1])
  477.                 {
  478.                     pPatchMeshData->m_bTexCoordsPresent = TRUE;
  479.                 }
  480.                 else
  481.                 {
  482.                     iTextureIndex = 0xFFFFFFFF;
  483.                 }
  484.             }
  485.  
  486.             if (rgbVertexReferencedArray[iRawVertexIndex] == FALSE)
  487.             {
  488.                 // first reference to this vertex.
  489.                 rgbVertexReferencedArray[iRawVertexIndex] = TRUE;
  490.  
  491.                 pPatchMeshData->m_rgVertices[iRawVertexIndex].iTextureIndex = iTextureIndex;
  492.             }
  493.             else
  494.             {
  495.                 // need to remember the index
  496.                 bFound = FindIdenticalPatchVertex(pPatchMeshData, iRawVertexIndex, iTextureIndex, &iNewVertex);
  497.  
  498.                 // if not found, then split out another vertex
  499.                 if (!bFound)
  500.                 {
  501.                     // realloc if array too small
  502.                     if (pPatchMeshData->m_cVertices == cVerticesMax)
  503.                     {
  504.                         cVerticesMax = cVerticesMax * 2;
  505.                         rgVerticesNew = new SPatchVertexData[cVerticesMax];
  506.                         if (rgVerticesNew == NULL)
  507.                         {
  508.                             hr = E_OUTOFMEMORY;
  509.                             goto e_Exit;
  510.                         }
  511.  
  512.                         memcpy(rgVerticesNew, pPatchMeshData->m_rgVertices, sizeof(SPatchVertexData) * pPatchMeshData->m_cVertices);
  513.  
  514.                         delete []pPatchMeshData->m_rgVertices;
  515.                         pPatchMeshData->m_rgVertices = rgVerticesNew;
  516.                     }
  517.  
  518.                     // grab the next spot in the array
  519.                     iNewVertex = pPatchMeshData->m_cVertices;
  520.                     pPatchMeshData->m_cVertices += 1;
  521.  
  522.                     // setup point rep and wedge list
  523.                     pPatchMeshData->m_rgVertices[iNewVertex].iPointRep = iRawVertexIndex;
  524.  
  525.                     // link into wedge list of point rep
  526.                     pPatchMeshData->m_rgVertices[iNewVertex].iWedgeList = pPatchMeshData->m_rgVertices[iRawVertexIndex].iWedgeList;
  527.                     pPatchMeshData->m_rgVertices[iRawVertexIndex].iWedgeList = iNewVertex;
  528.  
  529.                     // setup vertex info
  530.                     pPatchMeshData->m_rgVertices[iNewVertex].vPosition = pPatchMeshData->m_rgVertices[iRawVertexIndex].vPosition;
  531.                     pPatchMeshData->m_rgVertices[iNewVertex].iTextureIndex = iTextureIndex;
  532.                 }
  533.  
  534.                 // update the control point to the new vertex position
  535.                 pPatchMeshData->m_rgPatches[iPatch].m_rgdwControl[iPoint * 3] = iNewVertex;
  536.             }
  537.         }
  538.  
  539.     }
  540.  
  541. e_Exit:
  542.     delete []rgbVertexReferencedArray;
  543.  
  544.     return hr;
  545. }